package org.fastsyncer.manager.store;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.fastsyncer.common.constant.CommonConstant;
import org.fastsyncer.common.constant.MappingConstant;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.util.ApplicationUtil;
import org.fastsyncer.manager.util.FileUtil;
import org.fastsyncer.manager.util.SerializableUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 主要用来存储MappingTask配置信息和执行MappingTask错误日志
 * 
 * @author YangPei
 * @date 2017年5月17日 下午9:48:59
 * @version 1.0.0
 */
public class DataCenter {

	private static Logger logger = LoggerFactory.getLogger(DataCenter.class);

	private static DataCenter instance = new DataCenter();

	private static ConcurrentHashMap<String, Object> data = new ConcurrentHashMap<String, Object>();

	/**
	 * 存储路径
	 */
	private static String storePath = new File(ApplicationUtil.getKey(CommonConstant.MANAGER_STORE_PATH))
			.getAbsolutePath();

	/**
	 * 记录同步失败最大条数
	 */
	private static Integer maxRow = Integer.parseInt(ApplicationUtil.getKey(CommonConstant.MANAGER_STORE_MAX_ROW));

	private DataCenter() {
	}

	static {
		FileUtil.createDirIfNotExist(storePath);
		
		// 加载历史Mapping数据
		File[] list = new File(storePath).listFiles();
		logger.info("Load driver config path:" + storePath);
		if (list != null) {
			for (File f : list) {
				try {
					String mapping = f.getAbsolutePath() + File.separatorChar + f.getName()
							+ MappingConstant.STORE_MAPPING_SUFFIX;
					File file = new File(mapping);
					if (file.exists()) {
						MappingTask task = (MappingTask) SerializableUtil.deSerializable(file);
						data.put(task.getName(), task);
					}
				} catch (Exception e) {
					logger.error("加载历史Mapping配置时异常:" + e.getCause(), e.getClass());
				}
			}
		}
	}

	public static DataCenter getInstance() {
		return instance;
	}

	/**
	 * MappingTask配置关系
	 * 
	 * @param key
	 *            MappingTask名称
	 * @param value
	 *            MappingTask
	 * @return
	 */
	public boolean storeMapping(String key, Object value) {
		try {
			// 例如D:\fastsyncer\SourceDB_TargetDB
			String fileDir = storePath + File.separatorChar + key;
			// 检查文件夹
			FileUtil.createDirIfNotExist(fileDir);

			// 例如D:\fastsyncer\SourceDB_TargetDB\SourceDB_TargetDB.config
			String fileMapping = fileDir + File.separatorChar + key + MappingConstant.STORE_MAPPING_SUFFIX;
			// 序列化到磁盘
			SerializableUtil.serializable(new File(fileMapping), value);
			data.put(key, value);
			return true;
		} catch (Exception e) {
			logger.error("存储失败:" + e.getCause(), e.getClass());
		}
		return false;
	}

	/**
	 * 这里考虑到存储大量的错误数据没有意义，所以一致性要求不高<br />
	 * 
	 * @param key
	 *            MappingTask名称
	 * @param value
	 *            MappingTask
	 * @return
	 */
	public boolean storeMappingLog(String key, Object value) {
		try {
			// 例如D:\fastsyncer\SourceDB_TargetDB
			String fileDir = storePath + File.separatorChar + key;
			// 检查文件夹
			FileUtil.createDirIfNotExist(fileDir);

			// 例如D:\fastsyncer\SourceDB_TargetDB\SourceDB_TargetDB.data
			String fileHandle = fileDir + File.separatorChar + key + MappingConstant.STORE_HANDLE_SUFFIX;
			FileUtil.createFileIfNotExist(fileHandle);
			// 判断存储上限，上限就覆盖写入
			int currentFileRows = FileUtil.count(fileHandle);
			// true:追加,false:覆盖
			boolean isAppend = currentFileRows < maxRow ? true : false;
			FileUtil.save(fileHandle, value.toString(), isAppend);
			return true;
		} catch (Exception e) {
			logger.error("存储失败:" + e.getCause(), e.getClass());
		}
		return false;
	}

	public File getMappingLog(String key) {
		try {
			// 例如D:\fastsyncer\SourceDB_TargetDB
			String fileDir = storePath + File.separatorChar + key;
			// 检查文件夹
			FileUtil.createDirIfNotExist(fileDir);

			// 例如D:\fastsyncer\SourceDB_TargetDB\SourceDB_TargetDB.data
			String fileHandle = fileDir + File.separatorChar + key + MappingConstant.STORE_HANDLE_SUFFIX;
			FileUtil.createFileIfNotExist(fileHandle);

			return new File(fileHandle);
		} catch (Exception e) {
			logger.error("读取记录:" + e.getCause(), e.getClass());
		}
		return null;
	}

	/**
	 * 获取MappingTask配置
	 * 
	 * @param key
	 *            MappingTask名称
	 * @return MappingTask
	 */
	public Object getMapping(String key) {
		return data.get(key);
	}

	/**
	 * 获取所有的MappingTask配置
	 * 
	 * @param key
	 *            MappingTask名称
	 * @return MappingTask
	 */
	public List<Object> getMappingAll() {
		List<Object> maps = new ArrayList<Object>();
		for (Map.Entry<String, Object> entry : data.entrySet()) {
			maps.add(entry.getValue());
		}
		return maps;
	}

	/**
	 * 获取Mapping错误日志，默认最多获取最近1000条
	 * 
	 * @param key
	 *            MappingTask名称
	 * @param start
	 *            开始下标，从0开始
	 * @param size
	 *            显示条数
	 * @return
	 */
	public Object getMappingLog(String key, int start, int size) {
		// 例如D:\fastsyncer\SourceDB_TargetDB
		String fileDir = storePath + File.separatorChar + key;
		// 例如D:\fastsyncer\SourceDB_TargetDB\SourceDB_TargetDB.data
		String fileHandle = fileDir + File.separatorChar + key + MappingConstant.STORE_HANDLE_SUFFIX;
		return FileUtil.read(fileHandle, start, size);
	}

	/**
	 * 删除MappingTask
	 * 
	 * @param key
	 *            MappingTask名称
	 * @return
	 */
	public boolean remove(String key) {
		Object remove = data.remove(key);
		if (remove != null) {
			// 例如D:\fastsyncer\SourceDB_TargetDB
			String fileDir = storePath + File.separatorChar + key;
			FileUtil.deleteDir(new File(fileDir));
			return true;
		}
		return false;
	}
}
